package com.ruoyi.learn.java.concurrent;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;

import java.util.concurrent.Semaphore;

/**
 * 3. Semaphore（信号量）
 * 基本概念
 * 控制同时访问特定资源的线程数量
 *
 * 维护一组许可证，线程获取许可证才能执行，否则阻塞
 *
 * 可以用于实现资源池或限制并发数
 *
 * 主要方法
 * java
 * // 构造方法，permits表示许可数量
 * public Semaphore(int permits)
 *
 * // 公平模式构造方法
 * public Semaphore(int permits, boolean fair)
 *
 * // 获取许可（可获取多个）
 * public void acquire(int permits)
 *
 * // 释放许可（可释放多个）
 * public void release(int permits)
 *
 * // 尝试获取许可
 * public boolean tryAcquire()
 *
 * // 获取当前可用许可数
 * public int availablePermits()
 *
 * // 是否有线程正在等待获取许可
 * public boolean hasQueuedThreads()
 *
 * // 获取等待许可的线程数
 * public int getQueueLength()
 *
 *
 */
@Slf4j
public class SemaphoreDemo {
    public static void main(String[] args) {
        int permits = 2;
        Semaphore semaphore = new Semaphore(permits);

        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " 获取许可，执行任务");
                    log.info(Thread.currentThread().getName() + " 获取许可，执行任务");
                    try {
                        Thread.sleep(RandomUtils.nextLong(0, 6000));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                    System.out.println(Thread.currentThread().getName() + " 释放许可");
                    log.info(Thread.currentThread().getName() + " 释放许可");
                }
            }, "Thread-" + i).start();
        }
    }
}